/**
 * @author `wangxin 13700043840@163.com` 2020/4/17
 */
import settings from "@/settings";
// 注入：验证文件是否可以导入；
settings.merge({ injections: { importHandler: (fileName) => true } });
const importHandler = (fileName) => {
  try {
    return settings.injections.importHandler(fileName);
  } catch (ex) {
    console.error(ex.message);
    console.debug(`[debug] ${ex.stack}`);
  }
  return true;
}
const createInstance = (context, name) => {
  let instance;
  try {
    instance = context(name);
  } catch (ex) {
    console.error(ex.message);
    console.debug(`[debug] ${ex.stack}`);
  }
  return instance;
}
/** 资源导入器 */
export class Importer {
  /**
   * 装载资源导入器
   * @param {*} Vue Vue Component
   */
  install(Vue) {
    const { version, website } = settings;
    console.groupCollapsed(`${website.title} - ${version}`);
    const keys = Object.keys(website);
    const max = Math.max(...keys.map(p => p.length));
    keys.forEach(p => {
      console.debug(` - ${p}${' '.repeat(max - p.length + 2)}: ${website[p]}`);
    });

    this.Vue = Vue;
    this.__import_filter__();
    this.__import_directives__();
    this.__import_dictionaries__();
    this.__import_components__();
    this.__import_plugins__();
    console.groupEnd();
  }

  /** 导入过滤器 @private */
  __import_filter__() {
    const { Vue } = this
    const context = require.context('../../', true, /filters\/.+?.js$|apps\/.+?\/filters\/.+?.js$/);
    const keys = context.keys();
    if (keys.length == 0) {
      return;
    }
    console.groupCollapsed("-- filter --");
    keys.forEach(moduleName => {
      if (!importHandler(moduleName)) return;
      const instance = createInstance(context, moduleName);
      if (instance) {
        Object.keys(instance).forEach(key => {
          console.debug(`[debug] filter - ${key}`)
          Vue.filter(key, instance[key])
        })
      }
    })
    console.groupEnd();
  }

  /** 导入指令 @private */
  __import_directives__() {
    const { Vue } = this
    const context = require.context('../../', true, /apps\/.+?\/directives\/.+?.js$/);
    const keys = context.keys();
    if (keys.length == 0) {
      return;
    }
    console.groupCollapsed("-- directive --");
    keys.forEach(moduleName => {
      if (!importHandler(moduleName)) return;
      console.debug(`[debug] ${moduleName}`)
      try {
        const instance = context(moduleName);
        if (instance) {
          if (instance.default && instance.default.install) {
            console.debug(`[debug] directive - install - ${moduleName}`)
            Vue.use(instance.default);
          } else {
            Object.keys(instance).forEach(key => {
              console.debug(`[debug] directive - ${moduleName} - ${key}`)
              Vue.directive(key, instance[key])
            })
          }
        }
      } catch (ex) {
        console.error(ex.message);
        console.debug(`[debug] ${ex.stack}`);
      }
    })
    console.groupEnd();
  }

  /** 导入过滤器 @private */
  __import_dictionaries__() {
    const { Vue } = this
    const modules = [];
    const context = require.context('../../', true, /apps\/.+?\/dict.js$/);
    const keys = context.keys();
    if (keys.length > 0) {
      console.groupCollapsed("-- dictionary --");
      keys.forEach(moduleName => {
        if (!importHandler(moduleName)) return;
        console.debug(`[debug] ${moduleName}`)
        try {
          const instance = context(moduleName);
          if (instance) {
            Object.keys(instance).forEach(key => {
              console.debug(`[debug] dictionary - ${moduleName} - ${key}`)
              modules[key] = instance[key]
            })
          }
        } catch (ex) {
          console.error(ex.message);
          console.debug(`[debug] ${ex.stack}`);
        }
      });
      console.groupEnd();
    }
    Vue.prototype.$dict = {
      ...modules,
      convert: (k, v) => {
        let dict = Vue.prototype.$dict[k]
        if (!dict) {
          return `未找到数据字典[${k}]!`
        }
        let item = dict.find(p => {
          return p.value == v
        })
        if (item) {
          return item.text
        } else {
          return `dict[${k}] key[${v}] is not found!`
        }
      }
    }
  }

  /** 导入组件 @private */
  __import_components__() {
    const { Vue } = this
    const context = require.context('../../', true, /apps\/[a-z|A-z|-]*\/components\/[a-z|A-z|-]*\/[a-z|A-z|-]*\.vue$/);
    const keys = context.keys();
    if (keys.length == 0) {
      return;
    }
    console.groupCollapsed("-- component --");
    keys.forEach(moduleName => {
      if (!importHandler(moduleName)) return;
      if (moduleName.indexOf('pages') > -1) {
        return;
      }
      try {
        console.debug(`[debug] ${moduleName}`)
        const instance = context(moduleName);
        const component = instance && instance.default;
        if (component) {
          let name = component.name;
          if (!name) {
            const match = moduleName.match(/components\/(.+?)\/(.+?)\.vue/);
            let packageName = match[1];
            let fileName = match[2];
            if (fileName.toLowerCase() == 'index') {
              name = packageName;
            } else {
              name = fileName;
            }
          }
          console.debug(`[debug] components - ${name}`)
          Vue.component(name, component)
        }
      } catch (ex) {
        console.error(ex.message);
        console.debug(`[debug] ${ex.stack}`);
      }
    })
    console.groupEnd();
  }

  /** 导入插件 @private */
  __import_plugins__() {
    const { Vue } = this
    const context = require.context('../../', true, /apps\/.+?\/plugins\/.+?\/index.js$/);
    const keys = context.keys();
    if (keys.length == 0) {
      return;
    }
    console.groupCollapsed("-- plugin --");
    keys.forEach(moduleName => {
      if (!importHandler(moduleName)) return;
      console.debug(`[debug] ${moduleName}`)
      try {
        const instance = context(moduleName);
        const component = instance && instance.default;
        component && component.name && console.debug(`[debug] plugin - ${component.name}`)
        component && Vue.use(component);
      } catch (ex) {
        console.error(ex.message);
        console.debug(`[debug] ${ex.stack}`);
      }
    })
    console.groupEnd();
  }
}

/** Vuex.Store 导入器 */
class StoreImporter {
  constructor() {
    this.version = "0.1.0"
  }
  import() {
    const modules = {};
    let modulesFiles = require.context(
      '../../',
      true,
      /apps\/.+?\/lib\/api.js$|apps\/.+?\/lib\/state.js$/);
    modulesFiles.keys().forEach(moduleName => {
      if (!importHandler(moduleName)) return;
      try {
        const module = modulesFiles(moduleName);
        const instance = module && module.default;
        if (instance.actions) {
          let name = moduleName.replace(/^\.\/(.*)\.\w+$/, '$1');
          modules[name] = instance;
        } else {
          modules[moduleName] = { actions: instance };
        }
      } catch (ex) {
        console.error(ex.message);
        console.debug(`[debug] ${ex.stack}`);
      }
    });
    return modules;
  }
}

/** VueRouter导入器 */
class RouteImporter {
  constructor() {
    this.version = "0.1.0"
  }
  /**
   * 导入路由
   * @returns {Array} 返回路由清单
   */
  import() {
    let AppRoutes = [];
    let modulesFiles = require.context(
      '../../',
      true,
      /apps\/.+?\/lib\/route.js$/);
    modulesFiles.keys().forEach(p => {
      if (!importHandler(p)) return;
      try {
        const content = modulesFiles(p).default;
        content.forEach(g => {
          const route = AppRoutes.find(r => r.name === g.name);
          if (route) {
            route.children.push(...g.children);
          } else {
            AppRoutes.push(g);
          }
        });
      } catch (ex) {
        console.error(ex.message);
        console.debug(`[debug] ${ex.stack}`);
      }
    });
    return AppRoutes;
  }
}

const storeImporter = new StoreImporter();
const routeImporter = new RouteImporter();

export {
  storeImporter,
  routeImporter
}
